/**
 * @file avr/lock.h
 *
 * @brief Lock Bits API
 *  \par Introduction
 *
 *  The Lockbit API allows a user to specify the lockbit settings for the
 *  specific AVR device they are compiling for. These lockbit settings will be
 *  placed in a special section in the ELF output file, after linking.
 *
 *  Programming tools can take advantage of the lockbit information embedded in
 *  the ELF file, by extracting this information and determining if the lockbits
 *  need to be programmed after programming the Flash and EEPROM memories.
 *  This also allows a single ELF file to contain all the
 *  information needed to program an AVR.
 *
 *  To use the Lockbit API, include the <avr/io.h> header file, which in turn
 *  automatically includes the individual I/O header file and the <avr/lock.h>
 *  file. These other two files provides everything necessary to set the AVR
 *  lockbits.
 *
 *  \par Lockbit API
 *
 *  Each I/O header file may define up to 3 macros that controls what kinds
 *  of lockbits are available to the user.
 *
 *  If __LOCK_BITS_EXIST is defined, then two lock bits are available to the
 *  user and 3 mode settings are defined for these two bits.
 *
 *  If __BOOT_LOCK_BITS_0_EXIST is defined, then the two BLB0 lock bits are
 *  available to the user and 4 mode settings are defined for these two bits.
 *
 *  If __BOOT_LOCK_BITS_1_EXIST is defined, then the two BLB1 lock bits are
 *  available to the user and 4 mode settings are defined for these two bits.
 *
 *  If __BOOT_LOCK_APPLICATION_TABLE_BITS_EXIST is defined then two lock bits
 *  are available to set the locking mode for the Application Table Section
 *  (which is used in the XMEGA family).
 *
 *  If __BOOT_LOCK_APPLICATION_BITS_EXIST is defined then two lock bits are
 *  available to set the locking mode for the Application Section (which is used
 *  in the XMEGA family).
 *
 *  If __BOOT_LOCK_BOOT_BITS_EXIST is defined then two lock bits are available
 *  to set the locking mode for the Boot Loader Section (which is used in the
 *  XMEGA family).
 *
 *  The AVR lockbit modes have inverted values, logical 1 for an unprogrammed
 *  (disabled) bit and logical 0 for a programmed (enabled) bit. The defined
 *  macros for each individual lock bit represent this in their definition by a
 *  bit-wise inversion of a mask. For example, the LB_MODE_3 macro is defined
 *  as:
 *  \code
 *  #define LB_MODE_3  (0xFC)
 *  \endcode
 *
 *  To combine the lockbit mode macros together to represent a whole byte,
 *  use the bitwise AND operator, like so:
 *  \code
 *  (LB_MODE_3 & BLB0_MODE_2)
 *  \endcode
 *
 *  <avr/lock.h> also defines a macro that provides a default lockbit value:
 *  LOCKBITS_DEFAULT which is defined to be 0xFF.
 *
 *  See the AVR device specific datasheet for more details about these
 *  lock bits and the available mode settings.
 *
 *  A convenience macro, LOCKMEM, is defined as a GCC attribute for a
 *  custom-named section of ".lock".
 *
 *  A convenience macro, LOCKBITS, is defined that declares a variable, __lock,
 *  of type unsigned char with the attribute defined by LOCKMEM. This variable
 *  allows the end user to easily set the lockbit data.
 *
 *  \note If a device-specific I/O header file has previously defined LOCKMEM,
 *  then LOCKMEM is not redefined. If a device-specific I/O header file has
 *  previously defined LOCKBITS, then LOCKBITS is not redefined. LOCKBITS is
 *  currently known to be defined in the I/O header files for the XMEGA devices.
 *
 *  \par API Usage Example
 *
 *  Putting all of this together is easy:
 *
 *  \code
 *  #include <avr/io.h>
 *
 *  LOCKBITS = (LB_MODE_1 & BLB0_MODE_3 & BLB1_MODE_4);
 *
 *  int main(void)
 *  {
 *      return 0;
 *  }
 *  \endcode
 *
 *  Or:
 *
 *  \code
 *  #include <avr/io.h>
 *
 *  unsigned char __lock __attribute__((section (".lock"))) =
 *      (LB_MODE_1 & BLB0_MODE_3 & BLB1_MODE_4);
 *
 *  int main(void)
 *  {
 *      return 0;
 *  }
 *  \endcode
 *
 *
 *
 *  However there are a number of caveats that you need to be aware of to
 *  use this API properly.
 *
 *  Be sure to include <avr/io.h> to get all of the definitions for the API.
 *  The LOCKBITS macro defines a global variable to store the lockbit data. This
 *  variable is assigned to its own linker section. Assign the desired lockbit
 *  values immediately in the variable initialization.
 *
 *  The .lock section in the ELF file will get its values from the initial
 *  variable assignment ONLY. This means that you can NOT assign values to
 *  this variable in functions and the new values will not be put into the
 *  ELF .lock section.
 *
 *  The global variable is declared in the LOCKBITS macro has two leading
 *  underscores, which means that it is reserved for the "implementation",
 *  meaning the library, so it will not conflict with a user-named variable.
 *
 *  You must initialize the lockbit variable to some meaningful value, even
 *  if it is the default value. This is because the lockbits default to a
 *  logical 1, meaning unprogrammed. Normal uninitialized data defaults to all
 *  locgial zeros. So it is vital that all lockbits are initialized, even with
 *  default data. If they are not, then the lockbits may not programmed to the
 *  desired settings and can possibly put your device into an unrecoverable
 *  state.
 *
 *  Be sure to have the -mmcu=<em>device</em> flag in your compile command line and
 *  your linker command line to have the correct device selected and to have
 *  the correct I/O header file included when you include <avr/io.h>.
 *
 *  You can print out the contents of the .lock section in the ELF file by
 *  using this command line:
 *  \code
 *  avr-objdump -s -j .lock <ELF file>
 *  \endcode
 */

/*
 *  Copyright (c) 2007, Atmel Corporation
 *  All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in
 *   the documentation and/or other materials provided with the
 *   distribution.
 *
 * * Neither the name of the copyright holders nor the names of
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _AVR_LOCK_H_
#define _AVR_LOCK_H_  1

/**
 *  @defgroup avr_lock Lockbit Support
 *
 *  @ingroup avr
 */
/**@{*/

#ifndef __ASSEMBLER__

#ifndef LOCKMEM
#define LOCKMEM  __attribute__((section (".lock")))
#endif

#ifndef LOCKBITS
#define LOCKBITS unsigned char __lock LOCKMEM
#endif

#endif  /* !__ASSEMBLER */


/* Lock Bit Modes */
#if defined(__LOCK_BITS_EXIST)
#define LB_MODE_1  (0xFF)
#define LB_MODE_2  (0xFE)
#define LB_MODE_3  (0xFC)
#endif

#if defined(__BOOT_LOCK_BITS_0_EXIST)
#define BLB0_MODE_1  (0xFF)
#define BLB0_MODE_2  (0xFB)
#define BLB0_MODE_3  (0xF3)
#define BLB0_MODE_4  (0xF7)
#endif

#if defined(__BOOT_LOCK_BITS_1_EXIST)
#define BLB1_MODE_1  (0xFF)
#define BLB1_MODE_2  (0xEF)
#define BLB1_MODE_3  (0xCF)
#define BLB1_MODE_4  (0xDF)
#endif

#if defined(__BOOT_LOCK_APPLICATION_TABLE_BITS_EXIST)
#define BLBAT0 ~_BV(2)
#define BLBAT1 ~_BV(3)
#endif

#if defined(__BOOT_LOCK_APPLICATION_BITS_EXIST)
#define BLBA0 ~_BV(4)
#define BLBA1 ~_BV(5)
#endif

#if defined(__BOOT_LOCK_BOOT_BITS_EXIST)
#define BLBB0 ~_BV(6)
#define BLBB1 ~_BV(7)
#endif


#define LOCKBITS_DEFAULT (0xFF)

/**@}*/
#endif /* _AVR_LOCK_H_ */
